package com.example.basic.controller;

import com.example.basic.aop.OperationLogAnnotation;
import com.example.basic.constant.BaseConstants;
import com.example.basic.dao.UserMapper;
import com.example.basic.domain.User;
import com.example.basic.reslut.ResponseResult;
import com.example.basic.service.ExcelExport;
import com.example.basic.service.UserService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author mjw
 * @date 2022/8/25
 */
@RestController
@Api(tags = "user层的控制器")
@RequestMapping("/user")
@CrossOrigin
public class UserController {

    private final UserService userService;
    private final ExcelExport excelExport;
    private final UserMapper userMapper;

    @Autowired
    public UserController(UserService userService, ExcelExport excelExport, UserMapper userMapper) {
        this.userService = userService;
        this.excelExport = excelExport;
        this.userMapper = userMapper;
    }

    @OperationLogAnnotation(operModel = "用户模块-用户列表", operType = "查询", operDesc = "通过名字和年龄查询")
    @ApiOperation("通过名字和年龄查询user")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "姓名", required = true, paramType = "path"),
            @ApiImplicitParam(name = "age", value = "年龄", required = true, paramType = "path", dataType = "Integer")
    })
    @GetMapping("/getOne/{name}/{age}")
    public ResponseResult<User> findByNameAndAge(@PathVariable("name") String name,
                                                 @PathVariable("age") Integer age) {
        return ResponseResult.success(userService.findByNameAndAge(name, age));
    }

    @OperationLogAnnotation(operModel = "用户模块-用户列表", operType = "查询", operDesc = "查询所有用户")
    @ApiOperation("获取全部的user信息")
    @GetMapping("/getAll")
    public ResponseResult<PageInfo<User>> getAll(@RequestParam(value = "pageNum", required = false, defaultValue = "1") int pageNum,
                                                 @RequestParam(value = "pageSize", required = false, defaultValue = "20") int pageSize) {
        PageInfo<User> pageInfo = userService.selectAll(pageNum, pageSize);
        return ResponseResult.success(pageInfo);
    }

    @OperationLogAnnotation(operModel = "用户模块-用户列表", operType = "查询", operDesc = "根据性别查询")
    @ApiOperation("根据性别查询")
    @GetMapping("/selectBySex")
    public ResponseResult<List<User>> selectBySex(String sex) {
        List<User> users = userService.selectBySex(sex);
        return ResponseResult.success(users);
    }

    @OperationLogAnnotation(operModel = "用户模块-用户列表", operType = "查询", operDesc = "根据ID获取user信息")
    @ApiOperation("根据ID获取user信息")
    @GetMapping("/get/{id}")
    public ResponseResult<User> getById(@PathVariable("id") Integer id) {
        return ResponseResult.success(userService.selectById(id));
    }

    @OperationLogAnnotation(operModel = "用户模块-用户列表", operType = "添加", operDesc = "添加user信息")
    @ApiOperation("添加user信息")
    @PostMapping("/add")
    public ResponseResult<Integer> addUser(User user) {
        return ResponseResult.success(userService.addUser(user));
    }

    @OperationLogAnnotation(operModel = "用户模块-用户列表", operType = "批量添加", operDesc = "批量添加user信息")
    @ApiOperation("批量添加user信息")
    @PostMapping("/addBatch")
    public ResponseResult<Integer> addBatch(@RequestBody List<User> userList) {
        return ResponseResult.success(userService.addBatch(userList));
    }

    @OperationLogAnnotation(operModel = "用户模块-用户列表", operType = "修改", operDesc = "修改user信息")
    @ApiOperation("修改user信息")
    @PostMapping("/update")
    public ResponseResult<Integer> update(User user) {
        return ResponseResult.success(userService.update(user));
    }

    @OperationLogAnnotation(operModel = "用户模块-用户列表", operType = "删除", operDesc = "删除user信息")
    @ApiOperation("删除user信息")
    @PostMapping("/delete/{id}")
    public ResponseResult<Integer> delete(@PathVariable("id") Integer id) {
        Integer count = userService.deleteById(id);
        if (count > 0) {
            return ResponseResult.success(count);
        }
        return ResponseResult.fail(BaseConstants.FailConstants.DELETE_FAIL);
    }

    @OperationLogAnnotation(operModel = "用户模块-用户列表", operType = "批量删除", operDesc = "批量删除user信息")
    @ApiOperation("批量删除user信息")
    @PostMapping("/deleteBatch")
    @ApiImplicitParam(name = "idList", value = "idList", allowMultiple = true, dataTypeClass = List.class)
    public ResponseResult<Integer> deleteBatch(@RequestParam(value = "idList") List<Integer> idList) {
        Integer count = userService.deleteBatch(idList);
        if (count > 0) {
            return ResponseResult.success(count);
        }
        return ResponseResult.fail(BaseConstants.FailConstants.DELETE_FAIL);
    }

    @PostMapping("/export")
    public void export(HttpServletResponse response) {
        StopWatch sw = new StopWatch();
        sw.start();
        excelExport.export(response);
        sw.stop();
        System.out.println("sync export spend：" + sw.getTotalTimeMillis());
    }

    @PostMapping("/excel-export")
    public void exportExcel(HttpServletResponse response) {
        StopWatch sw = new StopWatch();
        sw.start();
        excelExport.exportExcel(response);
        sw.stop();
        System.out.println("async export spend：" + sw.getTotalTimeMillis());
    }

    @GetMapping("/testFindByIds")
    public ResponseResult<List<User>> testFindByIds() {
//        User user1 = User.builder().id(1).name("111").age(1).sex("1").description("111").build();
//        User user2 = User.builder().id(2).name("222").age(2).sex("2").description("222").build();
//        User user3 = User.builder().id(3).name("333").age(3).sex("3").description("333").build();
//        User user4 = User.builder().id(4).name("444").age(4).sex("4").description("444").build();
//        User user5 = User.builder().id(5).name("555").age(5).sex("5").description("555").build();
//        ArrayList<User> list = new ArrayList<>();
//        list.add(user1);
//        list.add(user2);
//        list.add(user3);
//        list.add(user4);
//        list.add(user5);
//        List<Integer> userIdList = list.stream().map(User::getId).collect(Collectors.toList());
        List<Integer> userIdList = new ArrayList<Integer>(){{
            add(10001);
        }};
        List<User> users = userService.findByIds(userIdList);
        return ResponseResult.success(users);
    }

    @GetMapping("/testFindByNames")
    public ResponseResult<List<User>> testFindByNames() {
        User user1 = User.builder().id(1).name("小明").age(1).sex("1").description("111").build();
        User user2 = User.builder().id(2).name("艾克").age(2).sex("0").description("222").build();
        User user3 = User.builder().id(3).name("333").age(3).sex("1").description("333").build();
        User user4 = User.builder().id(4).name("卡莎").age(4).sex("0").description("444").build();
        User user5 = User.builder().id(5).name("555").age(5).sex("1").description("555").build();
        ArrayList<User> list = new ArrayList<>();
        list.add(user1);
        list.add(user2);
        list.add(user3);
        list.add(user4);
        list.add(user5);
        List<String> userNameList = list.stream().map(User::getName).collect(Collectors.toList());
        System.out.println(userNameList);
        List<User> users = userService.findByNames(userNameList);
        System.out.println(users);
        return ResponseResult.success(users);
    }

    @PostMapping("/batch-import")
    public String batchImport(MultipartFile file) {
        String batchId = userService.batchImport(file);
        return batchId;
    }

    @GetMapping("/add-cycle")
    public void addCycle() {
        userService.addCycle();
    }

    @GetMapping("/select-by-thread")
    public List<User> selectByThread() {
        StopWatch sw = new StopWatch();
        sw.start();
        List<User> userList = userService.selectByThread();
        sw.stop();
        System.out.println("使用多线程查询数据库的耗时为：" + sw.getTotalTimeMillis());
        return userList;
    }

    @GetMapping("/select-no-thread")
    public List<User> selectNoThread() {
        StopWatch sw = new StopWatch();
        sw.start();
        List<User> userList = userService.selectNoThread();
        sw.stop();
        System.out.println("单线程查询数据库的耗时为：" + sw.getTotalTimeMillis());
        return userList;
    }

    @GetMapping("/select-by-partition")
    public List<User> selectByPartition() {
        StopWatch sw = new StopWatch();
        sw.start();
        List<User> userList = userService.selectByPartition();
        sw.stop();
        System.out.println("使用分区查询数据库的耗时为：" + sw.getTotalTimeMillis());
        return userList;
    }

    @PostMapping("/pdf")
    public void generatePdfDoc(HttpServletResponse response){
        try {
            userService.generatePdfDoc(response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
